﻿using System.Web;
using System.Configuration;
using System.Diagnostics;
using System;
using System.Collections.Generic;

namespace MicroDal.Context
{
    /// <summary>
    /// Http-module for accessing one session in the lifetime of one reques
    /// </summary>
    public class DataSessionHttpModule : IHttpModule
    {
        private static string MICRODAL_SESSION_ITEMS = "MicroDal DataSession items";

        /// <summary>
        /// Disposes all ressources
        /// </summary>
        public void Dispose()
        {
        }

        /// <summary>
        /// Called from ASP.NET runtime
        /// </summary>
        /// <param name="context"></param>
        public void Init(HttpApplication context)
        {
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }

            context.EndRequest += context_EndRequest;
        }

        void context_EndRequest(object sender, System.EventArgs e)
        {
            Tracer.WriteTrace("MicroDal.EndReques entered");
            var sessions = HttpContext.Current.Items[MICRODAL_SESSION_ITEMS] as IDictionary<string, DataSession>;
            if (sessions != null)
            {
                foreach (var key in sessions.Keys)
                {
                    sessions[key].Dispose();
                }
                Tracer.WriteTrace("MicroDal.EndReques sessions disposed");

            }
            HttpContext.Current.Items[MICRODAL_SESSION_ITEMS] = null;
        }

        /// <summary>
        /// Returns the current DataSession maintained for MicroDal. Either the connection named: MicroDalConnectionName or the first in the connectionstring section.
        /// </summary>
        public static DataSession GetCurrentSession()
        {
            Debug.Assert(HttpContext.Current != null);

            return GetSession(GetMicroDalConnectionName());
        }

        private static string GetMicroDalConnectionName()
        {
            var name = ConfigurationManager.AppSettings["MicroDalConnectionName"] ?? ConfigurationManager.ConnectionStrings[0].Name;
            if (string.IsNullOrEmpty(name))
                throw new ConfigurationErrorsException("There should be at least one database connection configured");

            return name;
        }

        internal static DataSession GetSession(string connectionname)
        {
            Debug.Assert(HttpContext.Current != null);

            var sessions = HttpContext.Current.Items[MICRODAL_SESSION_ITEMS] as IDictionary<string, DataSession>;
            
            if (sessions == null) 
                HttpContext.Current.Items[MICRODAL_SESSION_ITEMS] = sessions = new Dictionary<string, DataSession>();
            
            if (!sessions.ContainsKey(connectionname)) 
                sessions.Add(connectionname, new DataSession(connectionname));

            return sessions[connectionname];
        }
    }
}
